package summoning2;

import impsoft.bots.reflection.NPC;
import impsoft.bots.reflection.NPCIterator;
import impsoft.bots.reflection.PhysicalObject;
import impsoft.scripting.ibot.builtin.ocr.Menu;
import impsoft.scripting.ibot.itemrec.ItemContains;
import impsoft.scripting.ibot.structs.AryanTile;
import impsoft.utils.general.Timer;
import impsoft.utils.uber.UberClickOptions;
import impsoft.utils.uber.UberScriptUtils;

import java.awt.Rectangle;
import java.util.EnumSet;
import java.util.regex.Pattern;

import minimapbuttons.MiniMapButtonOption;
import potions.Potion;
import base.DreamScript;
import base.DreamUtility;

public class Summoning extends DreamUtility {
	private static final Rectangle summoningButton = new Rectangle(697, 137, 19, 14);

	public Summoning(DreamScript cs) {
		super(cs);
	}

	public boolean openFamiliarInventory() throws InterruptedException {
		if (isFamiliarSummoned() && getFamiliarName() != null) {
			return UberScriptUtils.clickWorldObject(cs, getFamiliar(),
					Pattern.compile(".*" + getFamiliarName() + ".*", Pattern.CASE_INSENSITIVE),
					Pattern.compile(".*Store.*", Pattern.CASE_INSENSITIVE),
					EnumSet.of(UberClickOptions.WALK_GAME_ONLY, UberClickOptions.USE_MENU)).possiblySuccessful();
		} else {
			return false;
		}
	}

	public NPC getFamiliar() {
		NPC closest = null;
		int distance = 1000;
		if (getFamiliarTime() > 0) {
			for (NPCIterator npci = cs.getNPCIterator(); npci.hasNext();) {
				NPC npc = npci.next();
				for (Familiar fs : Familiar.values()) {
					if (npc.getName().contains(fs.getName()) && npc.isInteractingWithMyPlayer()) {
						return npc;
					}
				}
			}
			for (NPCIterator npci = cs.getNPCIterator(); npci.hasNext();) {
				NPC npc = npci.next();
				for (Familiar fs : Familiar.values()) {
					if (npc.getName().contains(fs.getName()) && !npc.isInteractingWithOtherPlayer()
							&& npc.getLocation().distanceTo(cs.getLocation()) < distance) {
						closest = npc;
						distance = npc.getLocation().distanceTo(cs.getLocation());
					}
				}
			}
		}
		return closest;
	}

	public int getSummoningPoints() {
		try {
			return Integer.parseInt(cs.getInterfaceAtIndex(747, 5).getText());
		} catch (Throwable t) {
			return 0;
		}
	}

	public int getSpecialPoints() {
		return cs.getSettingArray()[1177];
	}

	public double getFamiliarTime() {
		return (double) (cs.getSettingArray()[1176] >> 6) / 2;
	}

	public boolean isFamiliarSummoned() {
		return getFamiliarTime() > 0;
	}

	public String getFamiliarName() throws InterruptedException {
		if (isFamiliarSummoned()) {
			return cs.getInterfaceAtIndex(662, 54).getText();
		} else {
			return null;
		}
	}

	public MiniMapButtonOption getSelectedMiniMapOption() {
		switch (cs.getSettingArray()[1493]) {
		case 0:
			return MiniMapButtonOption.FOLLOWER_DETAILS;
		case 1:
			return MiniMapButtonOption.SPECIAL_MOVE;
		case 2:
			return MiniMapButtonOption.ATTACK;
		case 3:
			return MiniMapButtonOption.CALL_FOLLOWER;
		case 4:
			return MiniMapButtonOption.DISMISS_FOLLOWER;
		case 5:
			return MiniMapButtonOption.TAKE_BOB;
		case 6:
			return MiniMapButtonOption.RENEW_FAMILIAR;
		}

		return null;
	}

	public boolean canSummonPouch(Familiar familiar) throws InterruptedException {
		return (getSummoningPoints() > 15 || hasRestoration())
				&& cs.theTabs.Inventory.count(familiar.getName() + " pouch") > 0;
	}

	// TODO: later
	public boolean renewFamiliar(Familiar familiar, boolean use_obelisk) throws InterruptedException {
		cs.theTabs.Inventory.setSelected();
		NPC f = getFamiliar();
		if (canSummonPouch(familiar)) {
			if (getSummoningPoints() < 15) {
				restorePoints(use_obelisk);
				Timer t = new Timer(1000);
				while (!t.isUp() && !canSummonPouch(familiar)) {
					cs.sleep(100);
				}
			}
			if (getSummoningPoints() > 15) {
				if (f != null && f.getName().equals(familiar.getName())) {
					if (!summoningButton.contains(cs.getCurrentMouseX(), cs.getCurrentMouseY())) {
						cs.mouseMove(summoningButton);
					}
					if (summoningButton.contains(cs.getCurrentMouseX(), cs.getCurrentMouseY())) {
						String tt = null;
						String action = "Renew";

						if ((tt = cs.theTopText.getTopText().toLowerCase()) != null
								&& (action == null || action == "" || tt.contains(action))) {
							cs.mouseClickLeft(cs.getCurrentMouseX(), cs.getCurrentMouseY());
							Timer t = new Timer(3000);
							while (!t.isUp() && getFamiliar() == null) {
								cs.sleep(100);
							}
							cs.log("[Summoning] Renewed familiar (" + familiar.getName() + ")");
							return true;
						} else {
							cs.mouseClickRight(cs.getCurrentMouseX(), cs.getCurrentMouseY());
							Timer t = new Timer(250);
							while (!t.isUp() && cs.theMenuFinder.getMenu() == null) {
								cs.sleep(50);
							}
							Menu m = null;
							if ((m = cs.theMenuFinder.getMenu()) != null) {
								if (!m.contains(action)) {

									cs.mouseClickLeft(cs.getCurrentMouseXY());
									return false;
								}
								if (m.clickContains(action)) {
									t = new Timer(3000);
									while (!t.isUp() && getFamiliar() == null) {
										cs.sleep(100);
									}
									cs.log("[Summoning] Renewed familiar (" + familiar.getName() + ")");
									return true;
								}
							}
						}
					}
				} else {
					if (getScript().getInventoryUtils()
							.doInventory(new ItemContains(familiar.getName() + " pouch"), "Summon", true)
							.isSuccessful()) {
						Timer t = new Timer(3000);
						while (!t.isUp() && getFamiliar() == null) {
							cs.sleep(100);
						}
						cs.log("[Summoning] Summoned familiar (" + familiar.getName() + ")");
						return true;
					}
				}
			}
		}
		return false;
	}

	public boolean hasRestoration() throws InterruptedException {
		return cs.theTabs.Inventory2.count("Summoning potion") > 0 || cs.theTabs.Inventory2.count("Super restore") > 0;
	}

	public boolean restorePoints(boolean useObelisk) throws InterruptedException {
		if (useObelisk) {
			cs.log("Using obelisk to restore summoning points");

			ObeliskFinder finder = new ObeliskFinder(getScript());
			AryanTile obeliskLocation = finder.getClosestObeliskLocation();

			cs.theWorldMap.walkTo(obeliskLocation);

			PhysicalObject obelisk = finder.getObeliskObject();
			if (obelisk != null) {

			} else {
				cs.log("Could not find obelisk");
			}
		} else {
			if (getScript().getPotionUtils().usePotion(Potion.SUMMONING)) {
				cs.log("Drinking summoning potion to restore summoning points");
				return true;
			} else if (getScript().getPotionUtils().usePotion(Potion.RESTORE)) {
				cs.log("Drinking restore potion to restore summoning points");
				return true;
			}
		}

		return false;
	}

}
